package com.cloud.custom.tasklist.service.impl;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.jdbc.SQL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.custom.common.consts.CustomConsts;
import com.cloud.custom.common.context.HumanSession;
import com.cloud.custom.common.utils.DateHelper;
import com.cloud.custom.common.utils.SessionHelper;
import com.cloud.custom.common.utils.SqlParserHelper;
import com.cloud.custom.tasklist.bean.TaskListSearchCriteria;
import com.cloud.custom.tasklist.bean.TaskListSearchField;
import com.cloud.custom.tasklist.entity.TaskList;
import com.cloud.custom.tasklist.entity.TaskListField;
import com.cloud.custom.tasklist.mapper.TaskListMapper;
import com.cloud.custom.tasklist.service.TaskListCacheService;
import com.cloud.custom.tasklist.service.TaskListService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

@Service
@Transactional
public class TaskListServiceImpl implements TaskListService {
	private static final Logger logger = LoggerFactory.getLogger(TaskListServiceImpl.class);

	@Autowired
	private TaskListMapper taskListMapper;

	@Autowired
	private TaskListCacheService taskListCacheService;

	@Override
	public PageInfo<Map<String, Object>> listTaskListData(TaskListSearchCriteria criteria) {
		TaskList taskList = taskListMapper.selectByPrimaryKey(criteria.getTaskListId());
		String sqlString = taskList.getTaskListSql();
		// 替换SQL文本中的EL表达式
		sqlString = SqlParserHelper.dynamicReplaceSQLEL(sqlString, this.sqlParams());
		SQL sqlBuilder = new SQL().SELECT("*").FROM("(" + sqlString + ") _temp_");
		// 条件过滤
		if (null != criteria.getSearchFields() && criteria.getSearchFields().size() > 0) {
			List<TaskListSearchField> searchFields = criteria.getSearchFields();
			for (TaskListSearchField searchField : searchFields) {
				if (null != searchField.getValue() && !"".equals(searchField.getValue())) {
					if (searchField.getType().equals(CustomConsts.SEARCH_FIELD_INPUT)) {
						// 文本框类型的条件
						sqlBuilder.WHERE(searchField.getColumnName() + " like '%" + searchField.getValue() + "%'");
					} else if (searchField.getType().equals(CustomConsts.SEARCH_FIELD_CALENDAR)) {
						// 日期类型的条件
						try {
							String date = (String) searchField.getValue();
							date = date.replace("Z", " UTC");
							SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
							Date searchDate = format.parse(date);
							String start = DateHelper.strToDateSql(
									DateHelper.dateTimeToStr(DateHelper.getDateBegin(searchDate)), 5,
									DateHelper.DB_TYPE_MYSQL);
							String end = DateHelper.strToDateSql(
									DateHelper.dateTimeToStr(DateHelper.getDateEnd(searchDate)), 5,
									DateHelper.DB_TYPE_MYSQL);

							sqlBuilder.WHERE(searchField.getColumnName() + " >= " + start + " and "
									+ searchField.getColumnName() + " <= " + end);
						} catch (Exception e) {
							logger.error("Unrecognized Date String: {}", searchField.getValue());
						}
					} else if (searchField.getType().equals(CustomConsts.SEARCH_FIELD_DROPDOWN)) {
						// 下拉框选择类型的条件
						@SuppressWarnings("unchecked")
						Map<String, Object> itemMap = (Map<String, Object>) searchField.getValue();
						Object value = itemMap.get("value");
						if (null != value) {
							sqlBuilder.WHERE(searchField.getColumnName() + " = '" + value + "'");
						}
					}
				}
			}
		}
		// 字段排序
		if (!StringUtils.isEmpty(criteria.getSortField())) {
			sqlBuilder.ORDER_BY(criteria.getSortField() + " " + criteria.getSortType());
		}
		if (logger.isDebugEnabled()) {
			logger.debug("TaskList Execute SQL: {}", sqlBuilder.toString());
		}
		sqlString = sqlBuilder.toString();
		final String sql = sqlString;
		PageInfo<Map<String, Object>> pageInfo = PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize())
				.doSelectPageInfo(() -> taskListMapper.selectByDynamicSQL(sql));
		// 字段格式化
		List<TaskListField> fields = taskListCacheService.listTaskListFields(criteria.getTaskListId());
		List<Map<String, Object>> lists = pageInfo.getList();
		for (Map<String, Object> record : lists) {
			for (TaskListField field : fields) {
				// 基础类型格式化：时间日期、数值、文本
				if (!StringUtils.isEmpty(field.getFieldFormat())) {
					Object o = record.get(field.getColumnName());
					record.put(field.getColumnName(), formatData(o, field.getFieldType(), field.getFieldFormat()));
				}
				// 枚举字典格式化
				if (!StringUtils.isEmpty(field.getFieldEnumFormat())) {
					// 从缓存获取字典常量，封装为Map
					Object o = record.get(field.getColumnName());
					if (null != o) {
						Map<String, String> revMap = taskListCacheService
								.listDictReverseMap(field.getFieldEnumFormat());
						String value = revMap.get(o.toString());
						if (!StringUtils.isEmpty(value)) {
							record.put(field.getColumnName(), value);
						}
					}
				}
			}
		}
		return pageInfo;
	}

	private String formatData(Object data, int dataType, String format) {
		if (null == data)
			return "";
		switch (dataType) {
		case 1:
			return String.format(format, data);
		case 2:
			return new DecimalFormat(format).format(data);
		case 3:
			return DateHelper.dateToFormatStr((Date) data, format);
		}
		return data + "";
	}

	private Map<String, String> sqlParams() {
		Map<String, String> keyValue = new HashMap<String, String>();
		HumanSession session = SessionHelper.get();
		keyValue.put(CustomConsts.CONTEXT_HUMAN_ID, session.getHumanId() + "");
		keyValue.put(CustomConsts.CONTEXT_HUMAN_ID_COLUMN, session.getHumanId() + "");

		keyValue.put(CustomConsts.CONTEXT_HUMAN_NAME, session.getHumanName() + "");
		keyValue.put(CustomConsts.CONTEXT_HUMAN_NAME_COLUMN, session.getHumanName() + "");

		keyValue.put(CustomConsts.CONTEXT_UNIT_ID, session.getUnitId() + "");
		keyValue.put(CustomConsts.CONTEXT_UNIT_ID_COLUMN, session.getUnitId() + "");

		keyValue.put(CustomConsts.CONTEXT_UNIT_NAME, session.getUnitId() + "");
		keyValue.put(CustomConsts.CONTEXT_UNIT_NAME_COLUMN, session.getUnitId() + "");

		keyValue.put(CustomConsts.CONTEXT_UNIT_CODE, session.getUnitCode() + "");
		keyValue.put(CustomConsts.CONTEXT_UNIT_CODE_COLUMN, session.getUnitCode() + "");

		List<Long> partIds = session.getRoleIds();
		if (null == partIds) {
			partIds = new ArrayList<Long>();
		}
		partIds.add(session.getHumanId());
		partIds.add(session.getUnitId());
		String parts = StringUtils.join(partIds, ",");
		keyValue.put(CustomConsts.CONTEXT_PART_ID, parts);
		keyValue.put(CustomConsts.CONTEXT_PART_ID_COLUMN, parts);

		return keyValue;
	}

}
